package com.jackstraw.jack_base.datasource.database.parten.base.service;

import com.jackstraw.jack_base.datasource.database.parten.base.dao.BaseDao;
import com.jackstraw.jack_base.datasource.database.parten.base.entity.page.PageData;
import com.jackstraw.jack_base.datasource.database.parten.base.entity.po.BasePo;
import com.jackstraw.jack_base.util.CollectionUtil;
import com.jackstraw.jack_base.util.JsonUtil;
import com.jackstraw.jack_base.util.ObjectUtil;
import com.jackstraw.jack_base.util.function.ReflectionUtil;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * 基础CRUD类
 *
 * @param <DAO> 持久层
 * @param <PO>  数据库实体类
 * @param <BO>  业务操作类
 * @param <ID>  主键（可以是基本数据类型，也可以为复合主键类）
 */
public interface CrudService<DAO extends BaseDao<PO>, PO extends BasePo<PO>, BO extends PO, ID> {
    /**
     * 批量提交时，每次提交数量
     */
    Integer BATCH_SIZE = 500;


    /**
     * 创建Po对象
     *
     * @return
     */
    default PO newPO() {
        return (PO) ReflectionUtil.newInstance(this.getClass(), 1);
    }


    /**
     * 创建Bo对象
     *
     * @return
     */
    default BO newBO() {
        return (BO) ReflectionUtil.newInstance(this.getClass(), 2);
    }


    /**
     * 创建Id对象
     *
     * @return
     */
    default ID newID() {
        return (ID) ReflectionUtil.newInstance(this.getClass(), 3);
    }

    /**
     * 获取对应 PO 的 BaseDao
     *
     * @return BaseDao
     */
    DAO getDao();

    /**
     * 获取 PO 的 class
     *
     * @return
     */
    Class<PO> getPoClass();

    /**
     * 获取 BO 的class
     *
     * @return
     */
    Class<BO> getBoClass();

    /**
     * 获取 DAO 的class
     *
     * @return
     */
    Class<DAO> getDaoClass();

    /**
     * 获取 ID 的class
     *
     * @return
     */
    Class<ID> getIdClass();

    /**
     * 分页条件查询
     * <p>
     * 必须含有的参数为：
     * pageNum：页码（从0开始）
     * pageSize：每页记录数
     *
     * @param params
     * @return
     */
    PageData<BO> page(Map<String, Object> params);

    /**
     * 条件查询
     *
     * @param params
     * @return
     */
    List<BO> list(Map<String, Object> params);

    /**
     * 主键查询
     *
     * @param id
     * @return
     */
    BO get(ID id);

    /**
     * 通过ID集合查询
     *
     * @param idS
     * @return
     */
    List<BO> get(Collection<ID> idS);

    /**
     * 保存一条数据
     *
     * @param bo
     */
    void insert(BO bo);

    /**
     * 批量保存数据
     *
     * @param boS
     */
    List<BO> insertBatch(List<BO> boS);

    /**
     * 通过主键更新一条数据
     *
     * @param bo
     */
    void update(BO bo);

    /**
     * 批量修改数据
     * <p>
     * 通过每一个数据的主键进行修改
     *
     * @param boS
     */
    void updateBatch(List<BO> boS);

    /**
     * 通过主键删除一条数据
     *
     * @param id
     */
    void delete(ID id);

    /**
     * 通过主键批量删除数据
     *
     * @param idS
     */
    void deleteBatch(List<ID> idS);

    /**
     * 将po转换为bo
     *
     * @param po
     * @return
     */
    default BO toBo(PO po) {
        if (ObjectUtil.ObjectUtilByLang3.isEmpty(po)) {
            return null;
        }
        return JsonUtil.copyProperties(po, this.getBoClass());
    }

    /**
     * 将po转换为bo
     *
     * @param poList
     * @return
     */
    default List<BO> toBo(List<PO> poList) {
        if (ObjectUtil.ObjectUtilByLang3.isEmpty(poList)) {
            return new ArrayList<>();
        }
        return JsonUtil.copyProperties(poList, this.getBoClass());
    }

    /**
     * 将bo转换为po
     *
     * @param bo
     * @return
     */
    default PO toPo(BO bo) {
        if (ObjectUtil.ObjectUtilByLang3.isEmpty(bo)) {
            return null;
        }
        return JsonUtil.copyProperties(bo, this.getPoClass());
    }

    /**
     * 将bo转换为po
     *
     * @param boList
     * @return
     */
    default List<PO> toPo(List<BO> boList) {
        if (ObjectUtil.ObjectUtilByLang3.isEmpty(boList)) {
            return new ArrayList<>();
        }
        return JsonUtil.copyProperties(boList, this.getPoClass());
    }

    /**
     * 获取List<ID>
     *
     * @param poList
     * @return
     */
    default List<ID> poToKeyList(List<PO> poList) {
        if (CollectionUtil.isEmpty(poList)) {
            return new ArrayList<>();
        }
        return JsonUtil.copyProperties(poList, this.getIdClass());
    }

    /**
     * 获取List<ID>
     *
     * @param boList
     * @return
     */
    default List<ID> boToKeyList(List<BO> boList) {
        if (CollectionUtil.isEmpty(boList)) {
            return new ArrayList<>();
        }
        return JsonUtil.copyProperties(boList, this.getIdClass());
    }

    default Class<DAO> currentDAOClass() {
        return ReflectionUtil.getClassGenricType(this.getClass(), 0);
    }

    default Class<PO> currentPOClass() {
        return ReflectionUtil.getClassGenricType(this.getClass(), 1);
    }

    default Class<BO> currentBOClass() {
        return ReflectionUtil.getClassGenricType(this.getClass(), 2);
    }

    default Class<ID> currentIDClass() {
        return ReflectionUtil.getClassGenricType(this.getClass(), 3);
    }

}
